package design.mode.singleton;

import java.util.concurrent.atomic.AtomicLong;

/**
 * 双重检测
 *
 * @author ZhongMingde on 2021/10/25
 */

public class LazyDoubleCheckSingleton {

    private AtomicLong id = new AtomicLong(0);

    private static LazyDoubleCheckSingleton instance;

    private LazyDoubleCheckSingleton() {

    }

    /**
     * <p>当第一个线程调用getInstance（）方法时，第二个线程也可以调用。当第一个线程执行到synchronized时会上锁，第二个线程就会变成MONITOR状态，出现阻塞。此时，阻塞并不是基于整个LazyDoubleCheckSingleton类的阻塞，而是在getInstance（）方法内部的阻塞，只要逻辑不太复杂，对于调用者而言感觉不到。</p>
     *
     * @return
     */
    public static LazyDoubleCheckSingleton getInstance() {
        // 如果实例未被创建，需要进入创建逻辑
        if (instance == null) {
            // 阻塞并不是基于整个LazyDoubleCheckSingleton类的阻塞，而是在getInstance（）方法内部的阻塞，只要逻辑不太复杂，对于调用者而言感觉不到。
            synchronized (LazyDoubleCheckSingleton.class) {
                // 再次检查是否需要创建实例
                if (instance == null) {
                    instance = new LazyDoubleCheckSingleton();
                }
            }
        }
        return instance;
    }

    public long getId() {
        return id.incrementAndGet();
    }
}
